package v1

import (
	"encoding/base64"
	"strings"
	"yuanxin-admin/internal/common/auth"
	"yuanxin-admin/internal/dto"
	"yuanxin-admin/internal/model"
	"yuanxin-admin/internal/repository"
	"yuanxin-admin/internal/vo"

	"gitee.com/botaoshow/yuanxin/web/common/database"
	"gitee.com/botaoshow/yuanxin/web/response"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

type SysUrlController struct {
}

func NewSysUrlController() *SysUrlController {
	return &SysUrlController{}
}

func (s *SysUrlController) QueryList(c *gin.Context) {
	keyword := c.DefaultQuery("keyword", "")
	q := repository.SysURL.WithContext(c)
	if keyword != "" {
		keyword = "%" + keyword + "%"
		q.Where(repository.SysURL.HTTPURL.Like(keyword)).
			Or(repository.SysURL.ClassName.Like(keyword)).
			Or(repository.SysURL.Method.Like(keyword))
	}
	q = q.Order(repository.SysURL.HTTPURL.Asc())
	list, err := q.
		Find()
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	response.Success(c, list)
}

func (s *SysUrlController) QueryWithRolesList(c *gin.Context) {
	sql := `
select
        sys_url.id,sys_url.http_method,sys_url.http_url,
        class_name,method,created_at,
        case when sys_url_whitelist.id is null then 'n' else 'y' end as in_whitelist,
        case sys_url_whitelist.allow_anonymous when '0' then 'y' else 'n' end as allow_anonymous
        from sys_url
        LEFT JOIN sys_url_whitelist ON sys_url_whitelist.url_id = sys_url.id
        `
	keyword := c.DefaultQuery("keyword", "")

	if keyword != "" {
		keyword = "'%" + keyword + "%'"
		wsql := `
 where sys_url.id like ?
                or sys_url.http_method like ?
                or sys_url.http_url like ?
                or sys_url.class_name like ?
                or sys_url.method like ?
`
		wsql = strings.ReplaceAll(wsql, "?", keyword)
		sql += wsql
	}
	sql += ` order by http_url asc`
	var rawData []*vo.SysUrlVO
	database.Db.Raw(sql).Scan(&rawData)
	for _, item := range rawData {
		var rlist []*model.SysRole
		id := item.ID
		err := repository.SysRoleURL.WithContext(c).
			Select(repository.SysRole.ALL).
			LeftJoin(repository.SysRole, repository.SysRole.ID.EqCol(repository.SysRoleURL.RoleID)).
			Where(repository.SysRoleURL.URLID.Eq(id)).
			Order(repository.SysRole.RoleCode.Asc()).
			Scan(&rlist)
		if err != nil {
			response.Fail(c, err.Error())
			return
		}
		item.SysRoles = rlist
	}
	response.Success(c, rawData)
}

func (s *SysUrlController) AddUrlToWhitelist(c *gin.Context) {
	var dtos []*dto.SysUrlWhitelistDTO
	err := c.ShouldBindJSON(&dtos)
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	var list []*model.SysURLWhitelist
	for _, sysUrlWhitelistDTO := range dtos {
		urlId := sysUrlWhitelistDTO.UrlId
		methodUrlBytes, _ := base64.URLEncoding.DecodeString(urlId)
		methodUrl := string(methodUrlBytes)
		arr := strings.Split(methodUrl, "<=>")
		allowAnonymous := sysUrlWhitelistDTO.AllowAnonymous
		sysUrlWhitelist := &model.SysURLWhitelist{
			ID:             uuid.NewString(), // 或使用其他UUID生成方法
			URLID:          urlId,
			HTTPMethod:     arr[0],
			HTTPURL:        arr[1],
			AllowAnonymous: allowAnonymous,
		}
		list = append(list, sysUrlWhitelist)
	}

	var urlIds []string
	for _, item := range list {
		urlIds = append(urlIds, item.URLID)
	}

	if len(urlIds) > 0 {
		_, _ = repository.SysURLWhitelist.WithContext(c).
			Where(repository.SysURLWhitelist.URLID.In(urlIds...)).
			Delete()
	}
	err = repository.SysURLWhitelist.WithContext(c).CreateInBatches(list, 100)
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	auth.FlushUrlWhitelistCache(c)
	response.SuccessDefault(c)

}

func (s *SysUrlController) RemoveUrlFormWhitelist(c *gin.Context) {
	var ids []string
	err := c.ShouldBindJSON(&ids)
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	_, err = repository.SysURLWhitelist.WithContext(c).
		Where(repository.SysURLWhitelist.ID.In(ids...)).
		Delete()
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	auth.FlushUrlWhitelistCache(c)
	response.SuccessDefault(c)
}

func (s *SysUrlController) QueryWhitelist(c *gin.Context) {
	keyword := c.DefaultQuery("keyword", "")
	q := repository.SysURLWhitelist.WithContext(c)
	if keyword != "" {
		keyword = "%" + keyword + "%"
		q = q.Where(repository.SysURLWhitelist.HTTPURL.Like(keyword)).
			Or(repository.SysURLWhitelist.AllowAnonymous.Like(keyword)).
			Or(repository.SysURLWhitelist.HTTPMethod.Like(keyword))
	}
	q = q.Order(repository.SysURLWhitelist.HTTPURL.Asc())
	list, err := q.
		Find()
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	response.Success(c, list)
}
